using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Text;
using System.Windows.Forms;
using System.Net;
using System.Net.Sockets;
using System.IO;
using System.Threading;

namespace collabr8
{
    public partial class ClientForm : Form
    {
        // Will hold the user name
        private Client client;
        private ViewerForm viewerForm = null;
        private ClientClipboardForm clipboardForm = null;
        private Thread thrReceive;
        public delegate void RefreshViewer();
        public delegate void ViewerClose();
        public RefreshViewer refreshDelegate;
        public ViewerClose closeDelegate;
        public delegate void DoSendClip(string fn);
        public DoSendClip delegateSendClip;
        public delegate void UpdateClip(string fn);
        public UpdateClip delegateUpdateClip;

        public ClientForm()
        {
            // On application exit, don't forget to disconnect first
            Application.ApplicationExit += new EventHandler(OnApplicationExit);
            InitializeComponent();
            // create the Client object:
            this.txtUser.Text = Environment.UserName;
            this.client = new Client(this);
            this.delegateSendClip = new DoSendClip(client.SendClip);
            this.closeDelegate = new ViewerClose(this.CloseViewer);
        }

        // The event handler for application exit
        public void OnApplicationExit(object sender, EventArgs e)
        {
            this.client.CloseConnection();
        }

        private void btnConnect_Click(object sender, EventArgs e)
        {
            // If we are not currently connected but awaiting to connect
            if (!client.isConnected)
            {
                if (txtMessage.Enabled)
                {
                    this.EndChat("You've been disconnected.");
                }
                else
                {
                    // Initialize the connection
                    if (!InitializeConnection())
                        txtLog.AppendText("Couldn't connect to server. \r\n");
                }
            }
            else // We are connected, thus disconnect
            {
                this.EndChat("You've been disconnected.");
            }
        }

        private bool InitializeConnection()
        {
           
            int port = Convert.ToInt32(txtPort.Text);

            if (this.client.Connect(txtIp.Text, port, txtUser.Text, txtPassword.Text))
            {
                // TODO: check parameters format.
                // Disable and enable the appropriate fields
                txtIp.Enabled = false;
                txtUser.Enabled = false;
                txtPassword.Enabled = false;
                txtPort.Enabled = false;
                txtMessage.Enabled = true;
                btnSend.Enabled = true;
                btnConnect.Text = "Disconnect";
                return true;
            }
            else
                return false;
        }


        // This method is called from a different thread in order to update the log TextBox
        public void UpdateLog(string strMessage)
        {
            // Append text also scrolls the TextBox to the bottom each time
            txtLog.AppendText(strMessage + "\r\n");
        }

        public void ShowViewer()
        {
                this.viewerForm = new ViewerForm(this, client.Ip, client.Port + 1, client.Width, client.Height);
                refreshDelegate = new RefreshViewer(viewerForm.Refresh);
                this.viewerForm.Show();
                this.thrReceive = new Thread(new ThreadStart(viewerForm.ReceiveVideo));
                this.thrReceive.IsBackground = true;
                this.thrReceive.Start();
        }

        public void CreateClipboard()
        {
            this.clipboardForm = new ClientClipboardForm(this);
            this.delegateUpdateClip = new UpdateClip(clipboardForm.AddItem);
            this.BtnClipboard.Cursor = Cursors.Hand;
        }

        // Closes a current connection
        public void EndChat(string Reason)
        {
            // Show the reason why the connection is ending
            txtLog.AppendText(Reason + "\r\n");
            // Enable and disable the appropriate controls on the form
            txtIp.Enabled = true;
            txtUser.Enabled = true;
            txtPassword.Enabled = true;
            txtPort.Enabled = true;
            txtMessage.Enabled = false;
            btnSend.Enabled = false;
            btnConnect.Text = "Connect";

            // Close the objects
            client.CloseConnection();
        }

        private void CloseViewer()
        {
            if (this.viewerForm != null)
            {
                this.viewerForm.Close();
            }
        }

        public ViewerForm Viewer
        {
            get
            {
                return viewerForm;
            }
            set
            {
                viewerForm = value;
            }
        }

        // We want to send the message when the Send button is clicked
        private void btnSend_Click(object sender, EventArgs e)
        {
            if (txtMessage.Lines.Length > 0)
            {
                try
                {
                    this.client.SendMessage(txtMessage.Text);
                } 
                catch
                {    
                    this.EndChat("Server is not responding. You've been disconnected.");
                }
            }
            txtMessage.Text = "";
        }

        // But we also want to send the message once Enter is pressed
        private void txtMessage_KeyPress(object sender, KeyPressEventArgs e)
        {
            // If the key is Enter
            if (e.KeyChar == (char)13)
            {
                if (txtMessage.Lines.Length > 0)
                {
                    try
                    {
                        this.client.SendMessage(txtMessage.Text);
                    }
                    catch
                    {
                        this.EndChat("Server is not responding. You've been disconnected.");
                    }
                }
                txtMessage.Text = "";
            }
        }

        public string UserName
        {
            get 
            {
                return this.txtUser.Text;
            }
        }

        private void clipBtn_Click(object sender, EventArgs e)
        {
            if (client.isConnected && this.clipboardForm != null)
            {
                this.clipboardForm.Show();
            } 
        }

        private void ClientForm_FormClosing(object sender, FormClosingEventArgs e)
        {
            this.client.CloseConnection();
        }
    }
}